package basis.lokal;

import java.io.IOException;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;

import basis.ea.EA;

/**
 * Lokalisierung von Meldungen und Texten in eine gewaehlte Sprache.
 * 
 * Datei: Lokalisierung.java                   
 * Datum: 06.11.2011   
 *                  
 * @author Alexander Bredo 
 * @version 0.5
 */
public class Lokalisierung
{
  private String zielsprache;
  private static HashMap<String, Sprache> sprachListe;


  /**
   * @deprecated Dieser Konstruktor ist ab der Spezifikation v1.1
   *             veraltet.
   */
  public Lokalisierung (String klassenbezeichnung, Sprachen sprache)
  {
    this (sprache.toString ());
  }

  
  /**
   * Erzeugt ein neues Lokalisierungs-Objekt fuer eine Zielsprache
   */
  public Lokalisierung (String zielsprache)
  {
    this.zielsprache = zielsprache.toLowerCase ();
    einlesen ();                          /* Aus gespeicherter Datei  */

    if (!sprachListe.containsKey (this.zielsprache))
    {
      /* Sprache muss geladen werden (oder nicht vorhanden)           */
      if (!existiertSprache (this.zielsprache))
      {
        throw new IllegalArgumentException (
            "Die gewuenschte Sprache ist nicht implementiert.");
      }
      else
      {
        sprachListe.put (this.zielsprache, 
            new Sprache (this.zielsprache));
      }
    }
  }


  /**
   * Prueft ob eine Sprache existiert
   */
  private static boolean existiertSprache (String sprache)
  {
    for (Sprachen s : Sprachen.values ())
    {
      if (sprache.equalsIgnoreCase (s.toString ()))
      {
        return true;
      }
    }
    return false;
  }


  /**
   * Gibt das Sprachobjekt der Zielsprache zurueck
   */
  private Sprache gibSprache ()
  {
    Sprache s = sprachListe.get (zielsprache);
    return s;
  }


  /**
   * Gibt das Datum in Langform aus.
   * Beispiel: Montag, 29. September 1997 21:54:46
   */
  public String gibFormatiertesDatumLang (Date datum)
  {
    return gibDatumsformatierer (true).format (datum);
  }


  /**
   * Gibt das Datum in Kurzform aus.
   * Beispiel: 29.9.1997 21:51
   */
  public String gibFormatiertesDatumKurz (Date datum)
  {
    return gibDatumsformatierer (false).format (datum);
  }


  /**
   * Gibt den Datumsformatierer entsprechend der Sprache zurueck
   */
  private DateFormat gibDatumsformatierer (boolean lang)
  {
    int datumsformat;
    int zeitformat;
    DateFormat formatierer;
    
    if (lang == true)
    {
      datumsformat = DateFormat.FULL;
      zeitformat = DateFormat.MEDIUM;
    }
    else
    {
      datumsformat = DateFormat.MEDIUM;
      zeitformat = DateFormat.SHORT;
    }
    /* Formatierer initialisieren                                       */
    formatierer = DateFormat.getDateTimeInstance (
        datumsformat, zeitformat, Locale.getDefault ());
    if (zielsprache.equalsIgnoreCase ("Deutsch"))
    {
      formatierer = DateFormat.getDateTimeInstance (
          datumsformat, zeitformat, Locale.GERMANY);
    }
    if (zielsprache.equalsIgnoreCase ("Englisch"))
    {
      formatierer = DateFormat.getDateTimeInstance (
          datumsformat, zeitformat, Locale.US);
    }
    if (zielsprache.equalsIgnoreCase ("Franzoesisch"))
    {
      formatierer = DateFormat.getDateTimeInstance (
          datumsformat, zeitformat, Locale.FRANCE);
    }
    return formatierer;
  }
  
  
  /**
   * Gibt die Zahl dem Land entsprechend formatiert aus
   */
  public String gibFormatiertenWert (double zahl)
  {
    return gibNummernformatierer ().format (zahl);
  }
  
  
  /**
   * Gibt den Zahlenformatierer entsprechend der Sprache zurueck
   */
  private NumberFormat gibNummernformatierer ()
  {
    NumberFormat formatierer = 
      NumberFormat.getInstance (Locale.getDefault ());
    
    if (zielsprache.equalsIgnoreCase ("Deutsch"))
    {
      formatierer = NumberFormat.getInstance (Locale.GERMANY);
    }
    if (zielsprache.equalsIgnoreCase ("Englisch"))
    {
      formatierer = NumberFormat.getInstance (Locale.UK);
    }
    if (zielsprache.equalsIgnoreCase ("Franzoesisch"))
    {
      formatierer = NumberFormat.getInstance (Locale.FRANCE);
    }
    return formatierer;
  }


  /**
   * Gibt die Uebersetzung eines Textes zurueck. Falls keine 
   * Uebersetzung existiert, wird der urspruengliche Text zurueckgegeben
   */
  public String gibUebersetzung (String text)
  {
    return gibSprache ().gibUebersetzung (text);
  }


  /**
   * Fuegt eine neue Uebersetzung eines Textes hinzu
   */
  public void uebersetzungHinzufuegen (String text, String uebersetzung)
  {
    gibSprache ().uebersetzungHinzufuegen (text, uebersetzung);
    speichern ();
  }


  /**
   * Loescht den angegebenen Text mit Uebersetzung aus der Liste
   */
  public void uebersetzungLoeschen (String text)
  {
    gibSprache ().uebersetzungLoeschen (text);
    speichern ();
  }


  /**
   * Speichert die Sprachdatei 
   */
  private synchronized void speichern ()
  {
    EA ea = new EA (gibDateiname ());
    
    try
    {
      ea.speichern (sprachListe);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }


  /**
   * Liest die Sprachdatei ein
   */
  private void einlesen ()
  {
    EA ea = new EA (gibDateiname ());
    Object objekt;
    
    if (sprachListe == null)
    {
      if (ea.istGespeichertesObjektVorhanden ())
      {
        try
        {
          objekt = ea.einlesen ();
          if (objekt instanceof HashMap<?, ?>)
          {
            /* 
             * Die nachfolgende Warnung ist darin begruendet, dass 
             * generische Datentypen zur Laufzeit nicht zur Verfuegung 
             * stehen. Das heisst sie werden vom Compiler entfernt und 
             * koennen zur Laufzeit bei der Typumwandlung nicht 
             * ueberprueft werden. 
             */
            sprachListe = (HashMap<String, Sprache>) objekt;
          }
          else
          {
            /* Darf im Normalfall nicht auftreten (ausser falsche Datei)*/
            sprachListe = new HashMap<String, Sprache> ();
          }
        }
        catch (ClassNotFoundException e)
        {
          e.printStackTrace();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
      }
      else
      {
        sprachListe = new HashMap<String, Sprache> ();
      }
    }
  }


  /**
   * Gibt den Dateiname fuer das aktuelle Objekt
   */
  private String gibDateiname ()
  {
    String bezeichnung = getClass ().getName ();
    return bezeichnung + "." + zielsprache;
  }

}
